package com.pavco.caribbeanvisit.client.presenter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.event.MarkerClickHandler;
import com.google.gwt.maps.client.event.MarkerClickHandler.MarkerClickEvent;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.Overlay;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;
import com.pavco.caribbeanvisit.client.RpcServiceAsync;
import com.pavco.caribbeanvisit.client.event.CountryListBoxChangedEvent;
import com.pavco.caribbeanvisit.client.event.CountryListBoxChangedEventHandler;
import com.pavco.caribbeanvisit.client.event.ReceivedCountriesEvent;
import com.pavco.caribbeanvisit.client.event.ReceivedXmlEvent;
import com.pavco.caribbeanvisit.client.eventhandlers.ReceivedCountriesEventHandler;
import com.pavco.caribbeanvisit.client.eventhandlers.ReceivedXmlEventHandler;
import com.pavco.caribbeanvisit.client.ui.AttractionMarker;
import com.pavco.caribbeanvisit.client.ui.CountryMarker;
import com.pavco.caribbeanvisit.client.ui.PavcoMap;
import com.pavco.caribbeanvisit.shared.models.Attraction;
import com.pavco.caribbeanvisit.shared.models.Country;

public class MainPresenter implements Presenter {
  private RpcServiceAsync rpcService;
  private HandlerManager eventBus;
  private MainPresenter.Display display;
  
  private ArrayList<Country> countries;
  private HashMap<String, Overlay> countryMarkers;
  
  public interface Display {
    HasChangeHandlers getCountryListBox();
    int getSelectedIndex(ChangeEvent event);
    HasClickHandlers getShowButton();
    HasClickHandlers getClearButton();
    HasValue<Boolean> getDispCountryMarkerCheckBox();
    List<String> getSelectedCountries();
    List<String> getSelectedTags();
    PavcoMap getMap();
    
    void setMapCentre(float longitude, float latitude);
    void setMapOverlays(Overlay[] countries);
    void setMapWidgetsVisibility(Overlay[] widgets, boolean on);
    
    // Set countries for listbox
    void setCountries(String[] countryNames);
    
    Widget asWidget();
  }
  
  public MainPresenter(RpcServiceAsync rpcService, HandlerManager eventBus,
      MainPresenter.Display display) {
    this.rpcService = rpcService;
    this.eventBus = eventBus;
    this.display = display;
  }
  
  private void fetchCountries() {
    rpcService.getAllCountries(new AsyncCallback<ArrayList<Country>>() {

      @Override
      public void onFailure(Throwable caught) {
        display.setCountries(null);
      }

      @Override
      public void onSuccess(ArrayList<Country> result) {
        ReceivedCountriesEvent rce = new ReceivedCountriesEvent();
        rce.setCountries(result);
        eventBus.fireEvent(rce);
      }
    });
  }
  
  private MarkerClickHandler countryMarkerHandler = new MarkerClickHandler() {
    public void onClick(MarkerClickEvent markerClickEvent) {      
      CountryMarker sender = (CountryMarker)markerClickEvent.getSender();
      String url = "http://picasaweb.google.com/data/feed/api/user/pavelbyles3/album/"
      + sender.getName() + "?kind=photo&imgmax=200";
      rpcService.getFeedFeed(url, new AsyncCallback<String>() {

        @Override
        public void onFailure(Throwable caught) {
          // TODO Auto-generated method stub
          
        }

        @Override
        public void onSuccess(String result) {
          ReceivedXmlEvent rXmlE = new ReceivedXmlEvent();
          rXmlE.setData(result);
          eventBus.fireEvent(rXmlE);
        }
      });
    }
  };
  
  public void bind() {
    display.getCountryListBox().addChangeHandler(new ChangeHandler() {
      
      @Override
      public void onChange(ChangeEvent event) {
        int selectedIndex = display.getSelectedIndex(event);
        
        Country selectedCountry = countries.get(selectedIndex);
        display.getMap().setCenter(LatLng.newInstance(
            selectedCountry.getLatitude(),
            selectedCountry.getLongitude()));
      }
    });
    
    display.getDispCountryMarkerCheckBox().addValueChangeHandler(new ValueChangeHandler<Boolean>() {
      
      @Override
      public void onValueChange(ValueChangeEvent<Boolean> event) {
        CountryMarker[] markers = new CountryMarker[countryMarkers.size()];
        countryMarkers.values().toArray(markers);
        
        display.setMapWidgetsVisibility(markers, event.getValue());
      }
    });
  }
  
  private void bindListeners() {
    eventBus.addHandler(ReceivedCountriesEvent.TYPE, new ReceivedCountriesEventHandler() {
      
      @Override
      public void onReceived(ReceivedCountriesEvent event) {
        ArrayList<Country> result = event.getCountries();
        String[] countryTextArr = new String[result.size()];
        countries = new ArrayList<Country>();
        countryMarkers = new HashMap<String, Overlay>();
        for (int i = 0; i < result.size(); ++i) {
          Country c = result.get(i);
          countryTextArr[i] = c.getName();
          CountryMarker cm = new CountryMarker(c);
          cm.addMarkerClickHandler(countryMarkerHandler);
          countries.add(c);
          countryMarkers.put(c.getName(), cm);
        }
        Country[] countryArr = new Country[result.size()];
        result.toArray(countryArr);
        CountryMarker[] markerArr = new CountryMarker[result.size()];
        countryMarkers.values().toArray(markerArr);
        display.setCountries(countryTextArr);
        display.setMapOverlays(markerArr);
      }
      
      @Override
      public void onFailure(Throwable caught) {
        // TODO Auto-generated method stub
        
      }
    });
    
    eventBus.addHandler(ReceivedXmlEvent.TYPE, new ReceivedXmlEventHandler() {
      
      @Override
      public void onReceivedXml(ReceivedXmlEvent event) {
        /*if (null == event.getData()) {
          noPhoto();
          return;
        }
        Document doc = XMLParser.parse(event.getData());
        NodeList entryElements = doc.getElementsByTagName("entry");
        for (int i = 0; i < entryElements.getLength(); ++i) {
          Photo p = new Photo();
          Element entry = (Element) entryElements.item(i);
          Element content = (Element) entry.getElementsByTagName("content").item(0);
          p.setTitle(getElementTextValue(entry, "summary"));
          p.setUrl(getElementAttrTextValue(content, "src"));
          photoList.add(p);
        }
        if (centrePanel.getWidget() != null) {
          centrePanel.remove(centrePanel.getWidget());
        }
        if (0 == photoList.size()) {
          noPhoto();
          return;
        }
        Photo p = photoList.get(0);
        imageTitle.setHTML(p.getTitle());
        centreImg.setUrl(p.getUrl());
        centrePanel.add(centreImg);*/
      }
    });
  }
  
  public void go(final HasWidgets container) {
    // bind display to presenter
    bind();
    // bind listeners to eventbus
    bindListeners();
    container.clear();
    // set view
    container.add(display.asWidget());
    fetchCountries();
    //fetchCountriesWithTags();
    //fetchTagsWithCountries();
  }
}